package vip.ola.code.ctrl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import vip.ola.code.common.ctrl.BaseController;
import vip.ola.code.common.service.RpcCommonService;
import vip.ola.code.secruity.JwtUser;
import vip.ola.core.common.annotation.MethodLog;
import vip.ola.core.common.constant.CodeConstant;
import vip.ola.core.common.constant.Constant;
import vip.ola.core.common.constant.RetEnum;
import vip.ola.core.common.domain.BizResponse;
import vip.ola.core.common.domain.PayResponse;
import vip.ola.core.common.util.MyLog;
import vip.ola.core.entity.PayOrder;
import vip.ola.core.entity.code.CodeOrder;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Optional;

import static vip.ola.core.common.constant.CodeConstant.*;
import static vip.ola.core.common.constant.Constant.CODE_ROLE_NORMAL;
import static vip.ola.core.common.util.LocalDateTimeUtil.PATTERN_DATE_TIME;

@RestController
@RequestMapping(Constant.CODE_CONTROLLER_ROOT_PATH + "/order")
@PreAuthorize("hasRole('" + CODE_ROLE_NORMAL + "')")
public class OrderController extends BaseController {

    private final MyLog log = MyLog.getLog(OrderController.class);

    @Autowired
    private RpcCommonService rpcService;

    @RequestMapping("/list")
    public ResponseEntity<?> list(@DateTimeFormat(pattern = PATTERN_DATE_TIME) LocalDateTime startTime, @DateTimeFormat(pattern = PATTERN_DATE_TIME) LocalDateTime endTime,
                                  String username, String codeName, String orderNo, String mchOrderNo, String clientIp, Integer status) {
        CodeOrder order = getCodeOrder();
        order.setUsername(username);
        order.setCodeName(codeName);
        order.setStatus(status);
        order.setOrderNo(orderNo);
        order.setMchOrderNo(mchOrderNo);
        order.setClientIp(clientIp);
        order.setCreateTime(startTime);
        order.setUpdateTime(endTime);
        IPage<CodeOrder> page = rpcService.codeOrderService.list(getPageIndex(), getPageSize(), order);
        return ResponseEntity.ok(PayResponse.buildPageSuccess(page));
    }

    private CodeOrder getCodeOrder() {
        JwtUser user = getUser();
        CodeOrder order = new CodeOrder();
        Integer type = user.getType();
        if (CODE_USER_TYPE.equals(type)) {
            order.setUserId(user.getId());
            order.setAgentId(user.getAgentId());
            order.setCodeBusId(user.getCodeBusId());
        } else if (CODE_AGENT_TYPE.equals(type)) {
            order.setAgentId(user.getId());
            order.setCodeBusId(user.getCodeBusId());
        } else if (CodeConstant.CODE_CODE_SUB_TYPE.equals(type)) {
            order.setCodeBusId(user.getCodeBusId());
        } else if (CODE_CODE_TYPE.equals(type)) {
            order.setCodeBusId(user.getId());
        }
        return order;
    }

    @RequestMapping("/confirm")
    @MethodLog(remark = "确认订单")
    public ResponseEntity confirm(Long id) {
        JwtUser user = getUser();
        CodeOrder order = rpcService.codeOrderService.getById(id);
        if (order == null) {
            return ResponseEntity.ok(BizResponse.build(RetEnum.CODE_ORDER_NOT_EXIST));
        }
        Integer type = user.getType();
        if (order.getUserId().equals(user.getId())
                || (CODE_USER_TYPE.equals(type) && order.getUserId().equals(user.getId()))
                || (CODE_AGENT_TYPE.equals(type) && order.getAgentId().equals(user.getId()))
                || (CODE_CODE_SUB_TYPE.equals(type) && order.getCodeBusId().equals(user.getCodeBusId()))
                || (CODE_CODE_TYPE.equals(type) && order.getCodeBusId().equals(user.getId()))) {
            // 确认订单,计算收益,修改余额,保存流水等
            rpcService.codeOrderService.confirm(order);
        } else {
            return ResponseEntity.ok(BizResponse.build(RetEnum.CODE_ORDER_NOT_AUTH));
        }
        // 修改主系统订单状态
        String orderNo = order.getOrderNo();
        PayOrder payOrder = rpcService.rpcPayOrderService.findByPayOrderId(orderNo);
        if (ORDER_STATUS_INIT.equals(payOrder.getStatus().intValue()) || ORDER_STATUS_PAYING.equals(payOrder.getStatus().intValue())) { // 初始或支付中
            // 修改状态为支付成功,
            int updateCount = rpcService.rpcPayOrderService.updateStatus4Success(orderNo);
            log.info("[确认订单]将订单修改为支付成功,返回结果:{}, userId={}, username={}, orderNo={},", updateCount, user.getId(), user.getUsername(), orderNo);
            // 发送商户通知
            rpcService.rpcPayNotifyService.executePayNotify(orderNo);
        }
        return ResponseEntity.ok(PayResponse.buildSuccess());
    }

    @RequestMapping("/get")
    @MethodLog(remark = "订单详情")
    public ResponseEntity get(Long id) {
        JwtUser user = getUser();
        CodeOrder order = rpcService.codeOrderService.getById(id);
        if (order == null) {
            return ResponseEntity.ok(BizResponse.build(RetEnum.CODE_ORDER_NOT_EXIST));
        }
        Integer type = user.getType();
        if ((CODE_USER_TYPE.equals(type) && !order.getUserId().equals(user.getId()))
                || (CodeConstant.CODE_CODE_SUB_TYPE.equals(type) && !order.getCodeBusId().equals(user.getId()))
                || (CODE_CODE_TYPE.equals(type) && !order.getCodeBusId().equals(user.getId()))) {
            return ResponseEntity.ok(BizResponse.build(RetEnum.CODE_ORDER_NOT_AUTH));
        }
        return ResponseEntity.ok(PayResponse.buildSuccess(order));
    }

    @RequestMapping("/count")
    public ResponseEntity<?> count(@DateTimeFormat(pattern = PATTERN_DATE_TIME) LocalDateTime startTime, @DateTimeFormat(pattern = PATTERN_DATE_TIME) LocalDateTime endTime,
                                   CodeOrder order) {
        JwtUser user = getUser();
        if (CODE_USER_TYPE.equals(user.getType())) {
            order.setUserId(user.getId());
            order.setAgentId(user.getAgentId());
            order.setCodeBusId(user.getCodeBusId());
        } else if (CODE_AGENT_TYPE.equals(user.getType())) {
            order.setAgentId(user.getId());
            order.setCodeBusId(user.getCodeBusId());
        } else if (CodeConstant.CODE_CODE_SUB_TYPE.equals(user.getType())) {
            order.setCodeBusId(user.getCodeBusId());
        } else if (CODE_CODE_TYPE.equals(user.getType())) {
            order.setCodeBusId(user.getId());
        }
        order.setCreateTime(startTime);
        order.setUpdateTime(endTime);

        Map allMap = rpcService.codeOrderService.countAll(order);
        Map sucMap = rpcService.codeOrderService.countSuccess(order);
        Map failMap = rpcService.codeOrderService.countFail(order);

        JSONObject obj = new JSONObject();
        obj.put("allTotalCount", allMap.getOrDefault("totalCount", 0));                     // 所有订单数
        obj.put("allTotalAmount", allMap.getOrDefault("totalAmount", 0));                   // 总金额
        obj.put("successTotalCount", sucMap.getOrDefault("totalCount", 0));                 // 成功订单数
        obj.put("successTotalAmount", sucMap.getOrDefault("totalAmount", 0));               // 成功金额

        BigDecimal totalCodeBusProfit = new BigDecimal(Optional.ofNullable(sucMap.get("totalCodeBusProfit")).map(Object::toString).orElse("0"));
        BigDecimal totalAgentProfit = new BigDecimal(Optional.ofNullable(sucMap.get("totalAgentProfit")).map(Object::toString).orElse("0"));
        BigDecimal totalUserProfit = new BigDecimal(Optional.ofNullable(sucMap.get("totalUserProfit")).map(Object::toString).orElse("0"));
        if (CODE_CODE_TYPE.equals(user.getType()) || CODE_CODE_SUB_TYPE.equals(user.getType())) {
            obj.put("totalProfit", totalCodeBusProfit.add(totalAgentProfit).add(totalUserProfit));
        } else if (CODE_AGENT_TYPE.equals(user.getType())) {
            obj.put("totalProfit", totalAgentProfit.add(totalUserProfit));
        } else if (CODE_USER_TYPE.equals(user.getType())) {
            obj.put("totalProfit", totalUserProfit);
        }
        // obj.put("totalUserProfit", sucMap.getOrDefault("totalUserProfit", 0));              // 成功用户收入
        // obj.put("totalAgentProfit", sucMap.getOrDefault("totalAgentProfit", 0));            // 成功代理码商利润
        // obj.put("totalCodeBusProfit", sucMap.getOrDefault("totalCodeBusProfit", 0));        // 成功码商收入
        obj.put("failTotalCount", failMap.getOrDefault("totalCount", 0));                   // 未完成订单数
        obj.put("failTotalAmount", failMap.getOrDefault("totalAmount", 0));                 // 未完成金额
        return ResponseEntity.ok(PayResponse.buildSuccess(obj));
    }

}
